Flutter中的导航Navigation总结 您所在的位置:网站首页 flutter widget 生命周期 Flutter中的导航Navigation总结

Flutter中的导航Navigation总结

#Flutter中的导航Navigation总结| 来源: 网络整理| 查看: 265

在Flutter中导航到一个新页面,通常我们会使用Navigator.of(context).push()来处理,或者是调用pushNamed("\xxx"),pop()等 。

但是这里有几个问题,

需要使用到context,这就限制来导航的使用场景,必须要在一个Widget中;第二个问题是,如果在Widget中写导航相关的代码,那么就在UI层混入了逻辑层的代码,路由导航属于业务逻辑,这不利于有一个清晰的架构;所有的调用者都必须要清楚导航逻辑,这使得代码变得强耦合,一旦导航逻辑修改了,所有的调用处都需要修改;

所以,本文将使用get_it库和命名路由named-routing的方式来解决以上问题。

关于get_it,后面将再出一篇文章详细介绍。

命名路由named-routing

步骤:

在MaterialApp中有个onGenerateRoute属性,在这里指定一个方法generateRoute,方法接收一个RouteSettings参数,返回一个Route class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', onGenerateRoute: router.generateRoute, initialRoute: HomeViewRoute, home: HomeView(), ); } } 要导航的一些View class HomeView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center(child: Text('Home'),), ); } } class LoginView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center(child: Text('Login'),), ); } } 创建一个routing_constants.dart来管理所有的路由名称 const String HomeViewRoute = '/'; const String LoginViewRoute = 'login'; 创建router.dart,管理所有的路由逻辑 import 'package:flutter/material.dart'; import 'package:flutter_navigation/routing_constants.dart'; import 'package:flutter_navigation/view/HomeView.dart'; import 'package:flutter_navigation/view/LoginView.dart'; import 'package:flutter_navigation/view/UndefineView.dart'; Route generateRoute(RouteSettings settings) { switch (settings.name) { case HomeViewRoute: return MaterialPageRoute(builder: (context) => HomeView()); case LoginViewRoute: var loginArgument = settings.arguments; return MaterialPageRoute(builder: (context) => LoginView(argument: loginArgument)); default: return MaterialPageRoute( builder: (context) => UndefinedView(name: settings.name)); } } 要导航的时候,直接调用: 可以设置一个默认的路由页面UndefinedView,用于处理异常场景 import 'package:flutter/material.dart'; class UndefinedView extends StatelessWidget { final String name; const UndefinedView({Key key, this.name}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text('Route for $name is not defined'), ), ); } }

也可以像下面这样处理,但是不建议采用,因为下面的方式将导航的业务逻辑混入到了View层中,

return MaterialApp( title: 'Named Routing', onGenerateRoute: router.generateRoute, onUnknownRoute: (settings) => MaterialPageRoute( builder: (context) => UndefinedView( name: settings.name, )), initialRoute: HomeViewRoute, ); 关于跳转时,参数的传递和返回

调用:

在传递时,在路由管理类里加上传递参数的逻辑

switch (settings.name) { ... case LoginViewRoute: var loginArgument = settings.arguments; return MaterialPageRoute(builder: (context) => LoginView(argument: loginArgument)); }

同时修改LoginView的代码,来接收参数,

class LoginView extends StatelessWidget { final String argument; const LoginView({Key key, this.argument}) : super(key: key); @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { Navigator.pop(context, 'fromLogin'); return false; }, child: Scaffold( floatingActionButton: FloatingActionButton( onPressed: () { Navigator.pop(context, 'fromLogin'); }, ), body: Center( child: Text('Login $argument'), ), ), ); } }

这里使用到了WillPopScope这个Widget,这个就是用来重载系统的返回键的,其应该用在单个页面上,如果返回了false,那么就不响应系统的返回键,当然也可以加入自己的逻辑,返回一些参数。

到这里已经实现了统一管理导航的逻辑了,接下来实现不使用context来处理导航。

跳转时,不使用context

在Flutter中,GlobalKeys可用于访问StatefulWidget的状态,利用这一点,我们可以在context以外的地方来访问NavigatorState。

添加get_it库 get_it: ^3.0.0+1创建一个全局的Service Locator import 'package:get_it/get_it.dart'; import 'NavigateService.dart'; final GetIt locator = GetIt.instance; void setupLocator() { locator.registerSingleton(NavigateService()); } 创建一个NavigateService import 'package:flutter/material.dart'; class NavigateService { final GlobalKey navigatorKey = GlobalKey(debugLabel: 'navigate_key'); NavigatorState get navigator => navigatorKey.currentState; get pushNamed => navigator.pushNamed; get push => navigator.push; } 在runApp 之前初始化 void main() { setupLocator(); runApp(App()); } 在 MaterialApp 的 navigatorKey属性中 绑定NavigateService中的 GlobalKey import 'package:flutter/material.dart'; import 'package:flutter_navigation/router.dart' as router; import 'package:flutter_navigation/routing_constants.dart'; import 'package:flutter_navigation/service_locator.dart'; import 'package:flutter_navigation/view/HomeView.dart'; import 'NavigateService.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', onGenerateRoute: router.generateRoute, initialRoute: HomeViewRoute, navigatorKey: locator().navigatorKey, theme: ThemeData( primarySwatch: Colors.blue, ), home: HomeView(), ); } }

完整代码参考: https://github.com/chenyucheng97/flutter_navigation

参考: Flutter | 通过 ServiceLocator 实现无 context 导航 Flutter Navigation Cheatsheet - A Guide to Named Routing Navigate Without BuildContext in Flutter using a Navigation Service



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有